/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.udt.designtime.api.json;


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.inspur.edp.cef.designtime.api.json.CefNames;
import com.inspur.edp.cef.designtime.api.json.SerializerUtils;
import com.inspur.edp.udt.designtime.api.entity.UnifiedDataTypeDef;
import com.inspur.edp.udt.designtime.api.extension.*;

import java.io.IOException;
import java.util.Date;
import java.util.Map;


/**
 * UDT序列化基类
 */
public abstract class UdtSerializer extends JsonSerializer<UnifiedDataTypeDef> {
	protected boolean isFull = true;
	public UdtSerializer(){}
	public UdtSerializer(boolean full){
		isFull = full;
	}

	@Override
	public void serialize(UnifiedDataTypeDef dataType, JsonGenerator writer, SerializerProvider serializers) throws IOException {
		SerializerUtils.writeStartObject(writer);
		SerializerUtils.writePropertyValue(writer, UdtNames.Id, dataType.getId());
		SerializerUtils.writePropertyValue(writer, UdtNames.Code, dataType.getCode());
		SerializerUtils.writePropertyValue(writer, UdtNames.Name, dataType.getName());
		if(isFull||(dataType.getDescription()!=null&&!"".equals(dataType.getDescription())))
			SerializerUtils.writePropertyValue(writer, UdtNames.Description, dataType.getDescription());
		if(isFull||(dataType.getCreator()!=null&&!"".equals(dataType.getCreator())))
			SerializerUtils.writePropertyValue(writer, UdtNames.Creator, dataType.getCreator());
		if(isFull||(dataType.getBeLabel()!=null&&dataType.getBeLabel().size()>0))
			SerializerUtils.writePropertyValue(writer,UdtNames.BeLabel,dataType.getBeLabel());
		// todo: Cef runtime 引用
		//writeDateTime(writer, UdtNames.CreatedDate, dataType.getCreatedDate());
		if(isFull||(dataType.getModifier()!=null&&!"".equals(dataType.getModifier())))
			SerializerUtils.writePropertyValue(writer, UdtNames.Modifier, dataType.getModifier());
		// todo: Cef runtime 引用
		//  writeDateTime(writer, UdtNames.ModifiedDate, dataType.getModifiedDate());
		// 序列化到文件中的是dotnet的AssemblyName
		if(isFull||(dataType.getDotnetAssemblyName()!=null&&!"".equals(dataType.getDotnetAssemblyName())))
			SerializerUtils.writePropertyValue(writer, UdtNames.AssemblyName, dataType.getDotnetAssemblyName());
		if(isFull||!(dataType.getDotnetAssemblyName()+"."+dataType.getCode()).equals(dataType.getI18nResourceInfoPrefix()))
			SerializerUtils.writePropertyValue(writer, CefNames.I18nResourceInfoPrefix, dataType.getI18nResourceInfoPrefix());

		writeUdtExtendInfo(writer, dataType);
		writePropertyUseTypeInfos(writer, dataType);
		writeValidationInfos(writer, dataType);
		writeExtensions(writer,serializers,dataType);

		SerializerUtils.writeEndObject(writer);
	}

	private void writeExtensions(JsonGenerator writer, SerializerProvider serializers, UnifiedDataTypeDef dataType) {
		if(dataType.getUdtExtensions()==null||dataType.getUdtExtensions().isEmpty())
			return;
		SerializerUtils.writePropertyName(writer,UdtNames.Extensions);
		SerializerUtils.writeStartObject(writer);
		for(Map.Entry<String, BaseUdtExtension> entry:dataType.getUdtExtensions().entrySet())
		{
			SerializerUtils.writePropertyName(writer, entry.getKey());
			UdtExtensionConfig config = UdtExtensionConfigs.getInstance().getExtensionConfig(entry.getKey());
			try {
				BaseUdtExtensionSerializer deserializer= (BaseUdtExtensionSerializer) Class.forName(config.getSerclass()).newInstance();
				deserializer.serialize(entry.getValue(),writer,serializers);
			} catch (ClassNotFoundException e) {
				throw new RuntimeException();
			} catch (IllegalAccessException e) {
				throw new RuntimeException();
			} catch (InstantiationException e) {
				throw new RuntimeException();
			} catch (IOException e) {
				throw new RuntimeException();
			}
		}

		SerializerUtils.writeEndObject(writer);
	}

	private void writeValidationInfos(JsonGenerator writer, UnifiedDataTypeDef dataType) {
		if(isFull||(dataType.getValidations()!=null&&dataType.getValidations().size()>0)){
			SerializerUtils.writePropertyName(writer, UdtNames.ValidationInfos);
			SerializerUtils.WriteStartArray(writer);
			dataType.getValidations().stream().forEach(item -> SerializerUtils.writePropertyValue_Object(writer, item));
			SerializerUtils.WriteEndArray(writer);
		}
	}

	private void writePropertyUseTypeInfos(JsonGenerator writer, UnifiedDataTypeDef dataType) {
		if(isFull||(dataType.getPropertyUseTypeInfos()!=null&&dataType.getPropertyUseTypeInfos().size()>0)){
			SerializerUtils.writePropertyName(writer, UdtNames.PropertyUseTypeInfos);
			SerializerUtils.WriteStartArray(writer);
			dataType.getPropertyUseTypeInfos().forEach((key, value) -> SerializerUtils.writePropertyValue_Object(writer, value));
			SerializerUtils.WriteEndArray(writer);
		}
	}

	protected abstract void writeUdtExtendInfo(JsonGenerator writer, UnifiedDataTypeDef dataType);

	private void writeDateTime(JsonGenerator writer, String propName, Date date) {
		String jsonDate = UdtNames.DateTimeFormat.format(date);
		SerializerUtils.writePropertyValue(writer, propName, jsonDate);
	}
}
